<?php

/*
 * Copyright 2008 the original author or authors.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#namespace tehframework\annotations;

#use tehframework\testing\phpunit\TestCase;

require_once 'test/testHelper.php';

class DocBlockTest extends TestCase
{
	function testToStringReturnsStringRepresentatingOfObject()
	{
		$this->assertSame('', (string)new DocBlock());
	}
	
	function testToStringReturnsStringRepresentatingOfObject2()
	{
		$this->assertNotSame('', (string)new DocBlock(
			'Short',
			'Long',
			array('unknown' => array(new UnknownTag(new TagDefinition('unknown')))),
			array('Fake' => array(new FakeAnnotation()))
		));
	}
	
	function testHasShortDescriptionReturnsTrueIfGivenShortDescriptionWasNotNullOrEmpty()
	{
		$doc = new DocBlock('Foo');
		
		$this->assertTrue($doc->hasShortDescription());
	}
	
	function testHasShortDescriptionReturnsFalseIfGivenShortDescriptionWasNull()
	{
		$doc = new DocBlock(null);
		
		$this->assertFalse($doc->hasShortDescription());
	}
	
	function testHasShortDescriptionReturnsFalseIfGivenShortDescriptionWasEmpty()
	{
		$doc = new DocBlock('');
		
		$this->assertFalse($doc->hasShortDescription());
	}
	
	function testGetShortDescriptionReturnsStringPassedToConstructor()
	{
		$doc = new DocBlock('Foo');
		
		$this->assertSame('Foo', $doc->getShortDescription());
	}
	
	function testGetShortDescriptionReturnsNullIfPassedDescriptionWasNull()
	{
		$doc = new DocBlock(null);
		
		$this->assertNull($doc->getShortDescription());
	}
	
	function testGetShortDescriptionReturnsNullIfPassedDescriptionWasEmpty()
	{
		$doc = new DocBlock('');
		
		$this->assertNull($doc->getShortDescription());
	}
	
	function testHasLongDescriptionReturnsTrueIfGivenLongDescriptionWasNotNullOrEmpty()
	{
		$doc = new DocBlock(null, 'Foo');
		
		$this->assertTrue($doc->hasLongDescription());
	}
	
	function testHasLongDescriptionReturnsFalseIfGivenLongDescriptionWasNull()
	{
		$doc = new DocBlock(null, null);
		
		$this->assertFalse($doc->hasLongDescription());
	}
	
	function testHasLongDescriptionReturnsFalseIfGivenLongDescriptionWasEmpty()
	{
		$doc = new DocBlock(null, '');
		
		$this->assertFalse($doc->hasLongDescription());
	}
	
	function testGetLongDescriptionReturnsStringPassedToConstructor()
	{
		$doc = new DocBlock(null, 'Foo');
		
		$this->assertSame('Foo', $doc->getLongDescription());
	}
	
	function testGetLongDescriptionReturnsNullIfPassedDescriptionWasNull()
	{
		$doc = new DocBlock(null, null);
		
		$this->assertNull($doc->getLongDescription());
	}
	
	function testGetLongDescriptionReturnsNullIfPassedDescriptionWasEmpty()
	{
		$doc = new DocBlock(null, '');
		
		$this->assertNull($doc->getLongDescription());
	}
	
	function testHasAnyTagsReturnsFalseIfNoTagsWerePassedToConstructor()
	{
		$doc = new DocBlock();
		
		$this->assertFalse($doc->hasAnyTags());
	}
	
	function testHasAnyTagsReturnsTrueIfAtLeastOneTagWasPassedToConstructor()
	{
		$doc = new DocBlock(null, null,
			array(
				'author' => array(new UnknownTag(new TagDefinition('author', 'me')))
			)
		);
		
		$this->assertTrue($doc->hasAnyTags());
	}
	
	function testHasAnyTagsReturnsTrueIfAtLeastOneTagWasPassedToConstructor2()
	{
		$doc = new DocBlock(null, null, array(
			'author' => array(
				new UnknownTag(new TagDefinition('author', 'me')),
				new UnknownTag(new TagDefinition('author', 'you'))
			))
		);
		
		$this->assertTrue($doc->hasAnyTags());
	}
	
	function testIsTaggedWithReturnsFalseIfDocBlockDoesNotHaveRequestedTag()
	{
		$doc = new DocBlock();
		
		$this->assertFalse($doc->isTaggedWith('author'));
	}
	
	function testIsTaggedWithReturnsTrueIfDocBlockHasRequestedTag()
	{
		$doc = new DocBlock(null, null,
			array(
				'author' => array(new UnknownTag(new TagDefinition('author', 'me')))
			)
		);
		
		$this->assertTrue($doc->isTaggedWith('author'));
	}
	
	function testGetTagThrowsExceptionIfRequestedTagDoesNotExist()
	{
		$this->setExpectedException('OutOfRangeException');
		
		$doc = new DocBlock();
		$doc->getTag('author');
	}
	
	function testGetTagReturnsRequestedTagInstanceIfExists()
	{
		$doc = new DocBlock(null, null,
			array(
				'author' => array(new UnknownTag(new TagDefinition('author', 'me')))
			)
		);
		
		$this->assertSame('me', $doc->getTag('author')->getDocString());
	}
	
	function testGetTagReturnsFirstTagOfRequestedNameIfThereAreMultiple()
	{
		$doc = new DocBlock(null, null, array(
			'author' => array(
				new UnknownTag(new TagDefinition('author', 'me')),
				new UnknownTag(new TagDefinition('author', 'you'))
			))
		);
		
		$this->assertSame('me', $doc->getTag('author')->getDocString());
	}
	
	function testGetTagArrayThrowsExceptionIfRequestedTagDoesNotExist()
	{
		$this->setExpectedException('OutOfRangeException');
		
		$doc = new DocBlock();
		$doc->getTagArray('author');
	}
	
	function testGetTagArrayReturnsAllTagsOfRequestedName()
	{
		$tags = array(
			new UnknownTag(new TagDefinition('author', 'me')),
			new UnknownTag(new TagDefinition('author', 'you'))
		);
		
		$doc = new DocBlock(null, null, array('author' => $tags));
		
		$this->assertSame($tags, $doc->getTagArray('author'));
	}
	
	function testGetAllTagsReturnsTagNameToTagInstancesMapOfAllTags()
	{
		$tags = array(
			'author' => array(
				new UnknownTag(new TagDefinition('author', 'me')),
				new UnknownTag(new TagDefinition('author', 'you'))
			),
			'var' => array(
				new UnknownTag(new TagDefinition('var', 'stdClass'))
			)
		);
		
		$doc = new DocBlock(null, null, $tags);
		
		$this->assertSame($tags, $doc->getAllTags());
	}
	
	function testHasAnyAnnotationsReturnsFalseIfNoAnnotationsWerePassedToConstructor()
	{
		$doc = new DocBlock();
		
		$this->assertFalse($doc->hasAnyAnnotations());
	}
	
	function testHasAnyAnnotationsReturnsTrueIfAtLeastOneAnnotationWasPassedToConstructor()
	{
		$doc = new DocBlock(null, null, array(),
			array('FooBar' => array(new FooBarAnnotation()))
		);
		
		$this->assertTrue($doc->hasAnyAnnotations());
	}
	
	function testHasAnyAnnotationsReturnsTrueIfAtLeastOneAnnotationWasPassedToConstructor2()
	{
		$doc = new DocBlock(null, null, array(), array(
			'FooBar' => array(new FooBarAnnotation(), new FooBarAnnotation()))
		);
		
		$this->assertTrue($doc->hasAnyAnnotations());
	}
	
	function testIsAnnotatedWithReturnsFalseIfDocBlockDoesNotHaveRequestedAnnotation()
	{
		$doc = new DocBlock();
		
		$this->assertFalse($doc->isAnnotatedWith('FooBar'));
	}
	
	function testIsAnnotatedWithReturnsTrueIfDocBlockHasRequestedAnnotation()
	{
		$doc = new DocBlock(null, null, array(),
			array('FooBar' => array(new FooBarAnnotation()))
		);
		
		$this->assertTrue($doc->isAnnotatedWith('FooBar'));
	}
	
	function testGetAnnotationThrowsExceptionIfRequestedAnnotationDoesNotExist()
	{
		$this->setExpectedException('OutOfRangeException');
		
		$doc = new DocBlock();
		$doc->getAnnotation('FooBar');
	}
	
	function testGetAnnotationReturnsRequestedAnnotationInstanceIfExists()
	{
		$doc = new DocBlock(null, null, array(),
			array('FooBar' => array(new FooBarAnnotation()))
		);
		
		$this->assertType('FooBarAnnotation', $doc->getAnnotation('FooBar'));
	}
	
	function testGetAnnotationReturnsFirstAnnotationOfRequestedNameIfThereAreMultiple()
	{
		$doc = new DocBlock(null, null, array(), array(
			'Fake' => array(new FakeAnnotation(1), new FakeAnnotation(2)))
		);
		
		$this->assertSame(1, $doc->getAnnotation('Fake')->getFoo());
	}
	
	function testGetAnnotationArrayThrowsExceptionIfRequestedAnnotationDoesNotExist()
	{
		$this->setExpectedException('OutOfRangeException');
		
		$doc = new DocBlock();
		$doc->getAnnotationArray('FooBar');
	}
	
	function testGetAnnotationArrayReturnsAllAnnotationsOfRequestedName()
	{
		$annotations = array(new FooBarAnnotation(), new FooBarAnnotation());
		
		$doc = new DocBlock(null, null, array(), array('FooBar' => $annotations));
		
		$this->assertSame($annotations, $doc->getAnnotationArray('FooBar'));
	}
	
	function testGetAllAnnotationsReturnsAnnotationNameToAnnotationInstancesMapOfAllAnnotations()
	{
		$annotations = array(
			'FooBar' => array(new FooBarAnnotation(), new FooBarAnnotation()),
			'Fake'   => array(new FakeAnnotation())
		);
		
		$doc = new DocBlock(null, null, array(), $annotations);
		
		$this->assertSame($annotations, $doc->getAllAnnotations());
	}
}